#include <sys/sysmacros.h> struct mpd { unsigned int d_id; /* id of memory segment */ caddr_t d_addr; /* address of allocated memory */ int d_npages; /* number of pages allocated */ struct mpd *d_last, *d_next; /* links */ }; struct mpd vdk_list; /* at init, this becomes a doubly /*linked ring */ int vdkmap(dev_t dev, vhandl_t *vt, off_t off, int len, int prot) { struct mpd *d; /* initial sanity checking (not shown) */ ... /* allocate some temporary storage */ if( (d = kmem_alloc(sizeof(struct mpd)), 0 ) == NULL ) return ENOMEM; d->d_npages = btoc(len); if( (d->d_addr = kmem_alloc(ctob(d->d_npages))KM_CACHEALIGN) == NULL ) { kmem_free(d,sizeof(struct mpd)); return ENOMEM; } /* map it into the user's address space */ if( v_mapphys(vt,d->d_addr,len) ) { kmem_free(d->d_addr,ctob(d->d_npages)); kmem_free(d,sizeof(struct mpd)); return ENOMEM; } d->d_id = v_gethandle(vt); /* initialize the memory */ bzero(d->d_addr,ctob(d->d_npages)); /* add to the list */ d->d_next = vdk_list.d_next; d->d_last = &vdk_list; d->d_next->d_last = d->d_last->d_next = d; return 0; }See "Returning Opaque Handle Data," for a description of the v_gethandle() system function. In the vdkunmap() function, you can find the piece of memory to be deallocated by searching the above list. The driver can then call the kmem_free() kernel function with the address and length of this section of memory:
int vdkunmap(dev_t dev, vhandl_t *vt) { struct mpd *d; int id; id = v_gethandle(vt); /* Find chunk of memory corresponding to it. */ for(d = vdk_list.d_next; d != &vdk_list ; d = d->d_next ) if( d->d_id == id ) break; /* Make sure we found it. */ if( d == &vdk_list ) return 0; /* remove from list */ d->d_next->d_last = d->d_last; d->d_last->d_next = d->d_next; /* free up resources */ kmem_free(d->d_addr,ctob(d->d_npages)); kmem_free(d,sizeof(struct mpd)); return 0; }